package com.hd.hdxgddcommon.utils.protocol;


import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Base64;

@Slf4j
public final class PushDataUtils {

    private static final boolean ENCRYPTION = true; // 指定应用接口是否加密（默认为true）

    private static final int SIGNATURE_LENGTH = 32; // 数字签名（字节数组C）占用字节数

    private static String INTERFACE_SIGN_TOKEN = "9543222D4C780962"; // 应用接口的signToken
    private static String INTERFACE_SECRET_KEY = "5A3A07C72F4ACD9769C13E9111420EA4"; // 应用接口的secretKey
    private static String APP_SIGN_TOKEN = "F1F7E786D5F88F88"; // APP的signToken
    private static String APP_SECRET_KEY = "3CCC7F1B7427DBD80D7D600C0044F980"; // APP的secretKey


    private PushDataUtils() {
    }

    /**
     * @param data      对应data字段
     * @param timestamp 对应timestamp字段
     * @return
     */

    public static byte[] encode(byte[] data, long timestamp, String key, String token) throws Exception {
        byte[] payload = data;
        byte[] recomputed = HmacSHA256Utils.digest(token, ByteUtils.concat(payload,
                ByteUtils.longToBytesBE(timestamp)));
        byte[] plaintext = ByteUtils.concat(recomputed, payload);
        plaintext = AESUtils.encryptECBPKCS5Padding(key, plaintext);
        byte[] encode = Base64.getEncoder().encode(plaintext);
        return encode;
    }

    public static byte[] encode(String data, long timestamp, String key, String token) throws Exception {
        byte[] payload = data.getBytes(StandardCharsets.UTF_8);
        return encode(payload, timestamp, key, token);
    }

    public static byte[] decode(String data, long timestamp, String key, String token) throws Exception {
        // 1. 校验消息时间戳, 一定程度防止重放攻击
        //
        // 2. Base64解码
        //
        // 3. 如项目加密属性为true, 解密之
        //
        // 4. 校验签名, 若成功, 才使用
        if (System.currentTimeMillis() > timestamp + 30000) { // 时间差不能超过30s
            return null;
        }

        byte[] plaintext = Base64.getDecoder().decode(data);

        if (ENCRYPTION) {
            plaintext = AESUtils.decryptECBPKCS5Padding(key, plaintext);
        }

        if (plaintext.length <= SIGNATURE_LENGTH) {
            return null;
        }

        byte[] signature = Arrays.copyOfRange(plaintext, 0, SIGNATURE_LENGTH);
        byte[] payload = Arrays.copyOfRange(plaintext, SIGNATURE_LENGTH, plaintext.length);
        byte[] recomputed = HmacSHA256Utils.digest(token, ByteUtils.concat(payload,
                ByteUtils.longToBytesBE(timestamp)));

        if (!Arrays.equals(signature, recomputed)) {
            return null;
        }
        return payload;
    }


}